import { RequestErrorType } from '../../request/service/request_handler'
import { StringUtils } from './string'

export class ErrorUtils {
  /**
   * 创建自定义错误
   */
  static createError(message: string, type: RequestErrorType = RequestErrorType.UNKNOWN): Error {
    const error = new Error(message)
    // 使用更标准的错误名称
    error.name = `${StringUtils.capitalizeFirstLetter(type)}Error`
    return error
  }

  /**
   * 创建取消错误
   */
  static createAbortError(message: string): Error {
    return this.createError(message, RequestErrorType.ABORT)
  }

  static getMessage(error: any): string {
    return error instanceof Error ? error.message : error instanceof Object ? error.message || '' : ''
  }

  /**
   * 获取错误类型
   */
  static getErrorType(error: any): RequestErrorType {
    const errorType = this.checkErrorTypes(error)
    return Object.keys(errorType).find(key => errorType[key as RequestErrorType]) as RequestErrorType || RequestErrorType.UNKNOWN
  }

  /**
   * 错误类型检查（返回布尔值对象）
   */
  static checkErrorTypes(error: unknown): Record<RequestErrorType, boolean> {
    const knownTypes = {
      permission: this.isPermission(error),
      cors: this.isCorsError(error),
      network: this.isNetworkError(error),
      timeout: this.isTimeoutError(error),
      parse: this.isParseError(error),
      validation: this.isValidationError(error),
      abort: this.isAbortError(error),
    }

    const unknown = Object.values(knownTypes).every(value => !value)

    return {
      ...knownTypes,
      unknown,
    }
  }

  static isPermission(error: unknown): boolean {
    if (!error)
      return false

    const errorObj = this.normalizeError(error)
    const message = errorObj.message.toLowerCase()
    const name = errorObj.name.toLowerCase()

    const permissionKeywords = [
      // 通用权限
      'permission',
      'permitted',
      'access denied',
      'access forbidden',
      'unauthorized',
      'forbidden',
      'not allowed',
      'insufficient permission',
      'privilege',
      'authorization',
      'security',

      // 浏览器/环境特定
      'blocked by client',
      'blocked by cors',
      'content security policy',
      'csp',
      'same-origin policy',
      'cross-origin',

      // 油猴/GM 特定
      'gm_xmlhttprequest',
      'grant',
      '@grant',
      'user script',
      'tampermonkey',
      'greasemonkey',

      // 网络权限
      'secure connection',
      'ssl',
      'certificate',
      'https',

      // 资源权限
      'local storage',
      'cookie',
      'session',
      'indexeddb',
      'filesystem',

      // API 权限
      'api key',
      'token',
      'authentication',
      'oauth',

      // 系统权限
      'administrator',
      'root',
      'sudo',
      'elevated',
    ]

    return (
    // 类型匹配
      errorObj.type === RequestErrorType.PERMISSION
      || errorObj.type === 'security'
      || errorObj.type === 'access'

      // 名称匹配
      || name.includes('permission')
      || name.includes('security')
      || name.includes('access')
      || name.includes('privilege')
      || /securityerror/i.test(name)
      || /accesserror/i.test(name)

      // 消息内容匹配
      || permissionKeywords.some(keyword => message.includes(keyword))

      // HTTP 状态码相关（403, 401）
      || message.includes('403')
      || message.includes('401')
      || message.includes('status code 403')
      || message.includes('status code 401')

      // 特定错误模式
      || /access.*denied/i.test(message)
      || /permission.*denied/i.test(message)
      || /not.*authorized/i.test(message)
      || /insufficient.*privilege/i.test(message)

      // 浏览器控制台常见权限错误
      || (message.includes('failed to execute') && message.includes('permission'))
      || message.includes('not allowed to')
      || message.includes('cannot access')

      // CORS 相关的权限错误
      || (message.includes('cors') && message.includes('blocked'))
      || (message.includes('origin') && message.includes('not allowed'))
    )
  }

  private static isCorsError(error: unknown): boolean {
    if (!error)
      return false

    const errorObj = this.normalizeError(error)
    const message = errorObj.message.toLowerCase()
    const name = errorObj.name.toLowerCase()

    return (
      errorObj.type === RequestErrorType.CORS
      || message.includes('cors')
      || message.includes('cross-origin')
      || message.includes('access-control')
      || name.includes('cors')
      // Fetch API 的 CORS 错误特征
      || message.includes('failed to fetch')
      || message.includes('networkerror')
      // XMLHttpRequest 的 CORS 错误
      || message.includes('origin')
      || message.includes('allow-origin')
    )
  }

  private static isNetworkError(error: unknown): boolean {
    if (!error)
      return false

    const errorObj = this.normalizeError(error)
    const message = errorObj.message.toLowerCase()
    const name = errorObj.name.toLowerCase()

    return (
      errorObj.type === RequestErrorType.NETWORK
      || /typeerror/i.test(name)
      || /networkerror/i.test(name)
      || message.includes('network')
      || message.includes('fetch')
      || message.includes('request')
      || message.includes('connection')
      || message.includes('socket')
      || message.includes('http')
      // 常见的网络错误消息
      || message.includes('failed')
      || message.includes('error')
      || message.includes('unable')
      || message.includes('cannot')
    )
  }

  private static isTimeoutError(error: unknown): boolean {
    if (!error)
      return false

    const errorObj = this.normalizeError(error)
    const message = errorObj.message.toLowerCase()
    const name = errorObj.name.toLowerCase()

    return (
      errorObj.type === RequestErrorType.TIMEOUT
      || /abortederror/i.test(name)
      || /timeouterror/i.test(name)
      || /aborterror/i.test(name)
      || message.includes('timeout')
      || message.includes('time out')
      || message.includes('timed out')
      || message.includes('abort')
      || message.includes('cancel')
    )
  }

  private static isParseError(error: unknown): boolean {
    if (!error)
      return false

    const errorObj = this.normalizeError(error)
    const message = errorObj.message.toLowerCase()
    const name = errorObj.name.toLowerCase()

    return (
      errorObj.type === RequestErrorType.PARSE
      || /syntaxerror/i.test(name)
      || message.includes('json')
      || message.includes('parse')
      || message.includes('syntax')
      || message.includes('invalid')
      || message.includes('unexpected token')
    )
  }

  private static isValidationError(error: unknown): boolean {
    if (!error)
      return false

    const errorObj = this.normalizeError(error)
    const message = errorObj.message.toLowerCase()

    return (
      errorObj.type === RequestErrorType.VALIDATION
      || message.includes('valid')
      || message.includes('invalid')
      || message.includes('format')
      || message.includes('malformed')
      || message.includes('url')
      || message.includes('parameter')
      || message.includes('argument')
    )
  }

  static isAbortError(error: unknown): boolean {
    if (!error)
      return false

    const errorObj = this.normalizeError(error)
    const message = errorObj.message.toLowerCase()
    const name = errorObj.name.toLowerCase()

    return (
      errorObj.type === RequestErrorType.ABORT
      || /aborterror/i.test(name)
      || message.includes('abort')
      || message.includes('cancel')
      || message.includes('stop')
      || message.includes('interrupt')
    )
  }

  /**
   * 标准化错误对象
   */
  private static normalizeError(error: unknown): { message: string, name: string, type?: string } {
    if (error instanceof Error) {
      const type = this.extractSafeType(error)

      return {
        message: error.message,
        name: error.name,
        type,
      }
    }

    if (typeof error === 'string')
      return { message: error, name: 'Error' }

    if (error && typeof error === 'object') {
      // 避免使用 || error 回退
      const message = this.extractSafeMessage(error)
      const name = this.extractSafeName(error)
      const type = this.extractSafeType(error)

      return { message, name, type }
    }

    return { message: String(error), name: 'UnknownError' }
  }

  /**
   * 安全提取错误消息
   */
  private static extractSafeMessage(error: object): string {
    const errorObj = error as any
    // 不使用 || error 回退，避免递归
    if (typeof errorObj.message === 'string')
      return errorObj.message
    if (typeof errorObj.error === 'string')
      return errorObj.error
    if (typeof errorObj.reason === 'string')
      return errorObj.reason

    // 安全序列化
    try {
      return JSON.stringify(error)
    }
    catch {
      return Object.prototype.toString.call(error)
    }
  }

  /**
   * 安全提取错误名称
   */
  private static extractSafeName(error: object): string {
    const errorObj = error as any
    if (typeof errorObj.name === 'string')
      return errorObj.name
    if (errorObj.constructor?.name)
      return errorObj.constructor.name
    return 'Error'
  }

  /**
   * 安全提取错误类型
   */
  private static extractSafeType(error: object): string | undefined {
    if (!error || typeof error !== 'object')
      return undefined

    //  检查标准 Error 的自定义属性
    if (error instanceof Error && 'type' in error) {
      const typeValue = (error as any).type
      return typeof typeValue === 'string' ? typeValue : undefined
    }

    //  检查普通对象的 type 属性
    if ('type' in error && typeof (error as any).type === 'string') {
      return (error as any).type
    }

    return undefined
  }
}
